package com.ibl.rover.lite.common.db;

import java.util.List;
import com.ibl.rover.lite.common.bean.BaseBean;

public class Criteria<T extends BaseBean> {

	private DatabaseManager databaseManager;
	private Class<T> bean;
	private StringBuilder where;
	private List<String> projection;
	private StringBuilder orderBy;

	Criteria(Class<T> bean, DatabaseManager entityManager) {
		this.bean = bean;
		this.orderBy = new StringBuilder();
		this.where = new StringBuilder();
		this.databaseManager = entityManager;
	}

	String getWhere() {
		return where.toString();
	}

	String getOrderBy() {
		return orderBy.toString();
	}

	String[] getProjection() {
		if (null != projection) {
			return (String[]) projection.toArray();
		}
		return null;
	}

	private enum ConjunctionOperators {
		or(" OR "), and(" AND ");
		private ConjunctionOperators(final String conjuctionOp) {
			this.conjunctionOp = conjuctionOp;
		}

		private String conjunctionOp;

		@Override
		public String toString() {
			return conjunctionOp;
		}
	}

	public enum Operators {
		isEqual(" = "), isNotEqual(" <> "), isGreater(" > "), isLess(" < "), isGreateAndEq(
				" >= "), isLessAndEq(" <= "), isLike(" LIKE "), isBetween(
				" BETWEEN ");

		private String operator;

		private Operators(final String operator) {
			this.operator = operator;
		}

		public String toSqlOperator() {
			return this.operator;
		}
	}

	public enum Operation {
		Select, Delete, Update
	}

	public void startCriteriaWithOr(final String colName, final Operators op,
			final long value) {
		where.append(" OR (");
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void startCriteriaWithOr(final String colName, final Operators op,
			final String value) {
		where.append(" OR (");
		where.append(colName + op.toSqlOperator() + "\'" + value + "\'");
	}

	public void startCriteriaWithOr(final String colName, final Operators op,
			final double value) {
		where.append(" OR (");
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void startCriteriaWithAnd(final String colName, final Operators op,
			final long value) {
		where.append(" AND (");
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void startCriteriaWithAnd(final String colName, final Operators op,
			final String value) {
		where.append(" AND (");
		where.append(colName + op.toSqlOperator() + "\'" + value + "\'");
	}

	public void startCriteriaWithAnd(final String colName, final Operators op,
			final double value) {
		where.append(" AND (");
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void endCriteria() {
		where.append(")");
	}

	public void addRestriction(final String colName, final Operators op,
			final double value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.or);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void addRestriction(final String colName, final Operators op,
			final long value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.or);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void addRestriction(final String colName, Operators op,
			final String value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.or);
		}
		where.append(colName + op.toSqlOperator() + "\'" + value + "\'");
	}

	public void addRestrictionWithOr(final String colName, Operators op,
			final String value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.or);
		}
		where.append(" OR " + colName + op.toSqlOperator() + "\'" + value
				+ "\'");
	}

	public void addRestrictionWithOr(final String colName, final Operators op,
			final double value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.or);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void addRestrictionWithOr(final String colName, final Operators op,
			final long value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.or);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void addRestrictionWithAnd(final String colName, Operators op,
			final String value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.and);
		}
		where.append(colName + op.toSqlOperator() + "\'" + value + "\'");
	}

	public void addRestrictionWithAnd(final String colName, final Operators op,
			final double value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.and);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void addRestrictionWithAnd(final String colName, final Operators op,
			final long value) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.and);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value));
	}

	public void addRestrictionWithAnd(final String colName, final Operators op,
			final long value, final long value2) {
		if (!where.toString().equals("")) {
			where.append(ConjunctionOperators.and);
		}
		where.append(colName + op.toSqlOperator() + String.valueOf(value)
				+ " AND " + String.valueOf(value2));
	}

	public void setOrderBy(String orderBy, boolean isAsc) {
		if (isAsc) {
			this.orderBy.append( orderBy + " ASC");
		} else {
			this.orderBy.append( orderBy +" DESC");
		}
	}

	// public List<T> execute(int startIndex, int count, int[] totalRecords)
	// throws BaseException {
	// return databaseManager.findBean(bean, where.toString(),
	// orderBy.toString(),
	// startIndex, count, totalRecords);
	// }

	public List<T> execute() throws BaseException {
		return databaseManager.findBean(bean, where.toString(),
				orderBy.toString());
	}

}
